#include <iostream>
#include <thread>
#include <future>
#include <memory>  // 智能指针头文件

// packaged_task使用示例
// 功能：将函数封装为可异步执行的任务，并通过future获取结果
int Add(int num1, int num2) 
{
    std::this_thread::sleep_for(std::chrono::seconds(3));  // 模拟耗时操作
    return num1 + num2;  // 返回计算结果
}

int main() 
{
   // 使用智能指针管理packaged_task的生命周期（关键点！）
   // 为什么需要智能指针：
   // 1. packaged_task不可拷贝
   // 2. 需要确保任务对象在异步执行期间保持有效
   auto ptask = std::make_shared<std::packaged_task<int(int,int)>>(Add);

   // 获取与任务关联的future对象
   std::future<int> fu = ptask->get_future();

   // 创建线程执行任务（通过lambda捕获智能指针）
   std::thread thr([ptask](){  // 值捕获保持引用计数
       // 解引用并执行封装的任务（注意参数传递）
       (*ptask)(11, 22);  // 实际调用Add(11, 22)
   });

   // 主线程阻塞等待结果（自动同步机制）
   int sum = fu.get();  // 若任务未完成则阻塞等待
   std::cout << "计算结果: " << sum << std::endl;  // 输出33

   // 等待工作线程结束
   thr.join();

   return 0;
}

/*
关键点解析：

1. packaged_task特性：
   - 模板类型需匹配函数签名：std::packaged_task<int(int,int)>
   - 将函数包装为可调用对象，并关联future
   - 任务只能移动（move），不能拷贝

2. 智能指针的作用：
   - 保证任务对象在线程执行期间有效
   - 通过shared_ptr的引用计数机制自动管理生命周期
   - 避免悬垂指针问题（若直接使用栈对象可能导致析构后访问）

3. 线程启动方式：
   - 使用lambda表达式捕获智能指针
   - 通过(*ptask)()解引用执行实际任务
   - 参数在调用时传递（11, 22）

4. 执行流程：
   (1) 创建packaged_task（堆内存）
   (2) 获取future对象
   (3) 启动线程执行任务
   (4) 主线程等待结果
   (5) 输出结果并等待线程结束
*/